#ifndef BAS_BAS_VECTOR_H
#define BAS_BAS_VECTOR_H

#include <stdbool.h>
#include <stdlib.h>
#include "bas/bas_const.h"
#include "bas/bas_iterator.h"
#include "bas/bas_vector_private.h"

/**
 * @brief     创建一个Vector动态数组
 * @param[in] tTypeInfo 类型信息, 使用_T()宏来得到类型信息，具体可以查看_T()宏的文档
 * @returns   指向Vector的指针, 创建失败返回NULL
 * @note      samples:
 *                1.不指定任何类型函数
 *                  T_Vector *ptVector = basVectorCreate(_T(T_YourStruct));
 *                2.指定销毁函数, 和拷贝函数(用于结构体中存在指针,需要自行进行释放, 以免内存泄露)                   
 *                  如果你需要一个销毁函数, 往往你也需要一个拷贝函数, 否则将会带来内存泄露
 *                  T_Vector *ptVector = basVectorCreate(_T(T_YourStruct, pfnDestory, pfnCopy));
 *                3.指定销毁函数, 拷贝函数, 小于比较函数, 初始化函数
 *                  T_Vector *ptVector = basVectorCreate(_T(T_YourStruct, pfnDestory, pfnCopy, pfnLess, pfnInit));
 *                4.元素为内置字符串类型
 *                  T_Vector *ptVector = basVectorCreate(_T(BUILDIN_STRING));
 */
T_Vector *basVectorCreate(const T_TypeInfo tTypeInfo);

/**
 * @brief     销毁Vector动态数组
 * @param[in] ptVector 指向Vector的指针
 */
void basVectorDestroy(T_Vector *ptVector);

/**
 * @brief     清空Vector动态数组, 删除其中所有的元素
 * @param[in] ptVector 指向Vector的指针
 */
void basVectorClear(T_Vector *ptVector);

/**
 * @brief     返回Vector中元素的个数
 * @param[in] ptVector 指向Vector的指针
 * @returns   Vector中元素的个数
 */
size_t basVectorSize(const T_Vector *ptVector);

/**
 * @brief     调整当前Vector中元素的个数为nSize个
 * @param[in] ptVector        指向Vector的指针
 * @param[in] nSize           调整后Vector中元素的个数
 * @param[in] pvInitParameter 可变参数为初始化函数的参数
 * @returns   0 - 成功　-1 - 失败
 * @note      1.如果nSize小于Vector中当前的元素个数, 则舍弃除了前nSize以后的所有元素, 并且调用销毁函数(如果有的话),
 *              此时指向被释放元素的迭代器失效
 *            2.如果nSize大于Vector中当前的元素个数, 则调整Vector的大小和容量, 多余的元素使用初始化函数进行初始化
 *              (如果未指定初始化函数, 默认填0), 可变参数为初始化函数的参数, 此时该操作可能使之前所有得到的迭代器失效
 *            3.如果nSize小于0, 什么也不做
 *            samples:
 *                1.未指定初始化函数
 *                  basVectorResize(ptVector, 10);
 *                2.指定了初始化函数
 *                  basVectorResize(ptVector, 10, pvInitParameter);
 */
#define basVectorResize(_ptVector, _nSize, ...) _basVectorResize(_ptVector, _nSize, ##__VA_ARGS__, BAS_PARM_END)

/**
 * @brief     测试Vector是否为空
 * @param[in] ptVector 指向Vector的指针
 * @returns   true - Vector为空　false - Vector不为空
 */
bool basVectorEmpty(const T_Vector *ptVector);

/**
 * @brief     返回Vector的容量
 * @param[in] ptVector 指向Vector的指针
 * @returns   Vector的容量
 */
size_t basVectorCapacity(const T_Vector *ptVector);

/**
 * @brief     调整Vector的容量
 * @param[in] ptVector  指向Vector的指针
 * @param[in] nCapacity 新的Vector容量
 * @returns   0 - 成功 -1 - 失败
 * @warning   该操作可能使之前所有得到的迭代器失效
 */
int basVectorReserve(T_Vector *ptVector, const size_t nCapacity);

/**
 * @brief     在Vector末尾添加一个新元素
 * @param[in] ptVector 指向Vector的指针
 * @param[in] element  对于内置类型, 该参数为内置类型本身, 对于用户定义的结构体类型,该参数为结构体指针
 * @returns   0 - 成功 -1 - 失败
 * @warning   该操作可能使之前所有得到的迭代器失效
 * @note      1.如果指定了拷贝函数, 则调用拷贝函数, 执行深拷贝, 请注意复杂类型导致的内存泄漏
 *            2.如果指定的类型的是BUILDIN_LONG, BUILDIN_LONGLONG, BUILDIN_LONGDOUBLE, 请注意传入常量的类型,
 *              比如对于BUILDIN_LONG, 要使用类似10L的常量(见sample 2), 请务必注意常量的类型, 否则存放到容器内的值是不正确的
 *            samples:
 *                1. basVectorPushBack(ptVector, 10);
 *                2. basVectorPushBack(ptVector, 10L);
 *                3. basVectorPushBack(ptVector, iValue);
 *                4. basVectorPushBack(ptVector, "Hello, world");
 *                5. basVectorPushBack(ptVector, caString);
 *                6. basVectorPushBack(ptVector, ptYourStruct);
 */
int basVectorPushBack(T_Vector *ptVector, ...);

/**
 * @brief     在Vector末尾删除一个元素, 并且调用销毁函数(如果有的话)
 * @param[in] ptVector 指向Vector的指针
 * @note      若Vector为空, 什么也不做
 * @warning   该操作使指向该元素的迭代器失效
 */
void basVectorPopBack(T_Vector *ptVector);

/**
 * @brief     使用下标随机访问Vector
 * @param[in] ptVector 指向Vector的指针
 * @param[in] iIndex   索引
 * @returns   返回指向数据的指针, 特别要注意BUILDIN_STRING类型, 返回值是(char *)的指针, 也就是(char **)
 * @note      1.下标从0开始 
 *            2.如果Vector为空返回NULL 
 *            3.如果下标超出Vector中实际元素的个数, 则取最后一个元素
 *            4.如果下标为负数, 表示从Vector最后向前取元素,例如basVectorAt(ptVector, -1), 取最后一个元素
 *            5.如果向前取的个数超过Vector中实际元素的个数, 则取第一个元素 
 * @warning   修改BUILDIN_STRING类型的返回值时, 请注意不能改变字符串长度, 否则将导致内存越界或者内存泄露
 */
void *basVectorAt(const T_Vector *ptVector, const int iIndex);

/**
 * @brief     返回指向Vector第一个元素的迭代器, 类型为随机迭代器
 * @param[in] ptVector 指向Vector的指针
 * @returns   指向Vector第一个元素的迭代器 
 */
T_Iterator basVectorBegin(const T_Vector *ptVector);

/**
 * @brief     返回指向Vector末尾(最后一个元素之后)的迭代器(哨兵迭代器), 类型为随机迭代器
 * @param[in] ptVector 指向Vector的指针
 * @returns   指向Vector末尾的迭代器
 * @note      返回的迭代器作为哨兵使用, 并不指向实际的元素
 */
T_Iterator basVectorEnd(const T_Vector *ptVector);

/**
 * @brief     返回指向Vector最后一个元素的迭代器, 类型为随机迭代器
 * @param[in] ptVector 指向Vector的指针
 * @returns   指向Vector最后一个元素的迭代器 
 */
T_Iterator basVectorRBegin(const T_Vector *ptVector);

/**
 * @brief     返回指向Vector开头(第一个元素之前)的迭代器(哨兵迭代器), 类型为随机迭代器
 * @param[in] ptVector 指向Vector的指针
 * @returns   指向Vector开头的迭代器
 * @note      返回的迭代器作为哨兵使用, 并不指向实际的元素
 */
T_Iterator basVectorREnd(const T_Vector *ptVector);

/**
 * @brief     在迭代器tIterator的位置前插入一个元素
 * @param[in] ptVector  指向Vector的指针
 * @param[in] tIterator 迭代器
 * @param[in] element  对于内置类型, 该参数为内置类型本身, 对于用户定义的结构体类型,该参数为结构体指针
 * @returns   指向新插入元素的迭代器, 如果失败返回无效迭代器, 使用basIteratorIsValid来检查返回值
 * @warning   该操作可能使之前所有得到的迭代器失效
 * @see       basIteratorIsValid basVectorPushBack
 */
T_Iterator basVectorInsert(T_Vector *ptVector, const T_Iterator tIterator, ...);

/**
 * @brief     清除迭代器tIterator所指向的元素 
 * @param[in] ptVector  指向Vector的指针
 * @param[in] tIterator 迭代器
 * @returns   指向被删除元素下一个元素的迭代器, 如果被删除元素是最后一个元素, 返回容器末尾的哨兵迭代器
 * @note      如果指定了销毁函数, 则在清除元素前会调用销毁函数
 */
T_Iterator basVectorErase(T_Vector *ptVector, const T_Iterator tIterator);

#endif
